<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>像黑客一样使用 Linux 命令行</title>
    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Anonymous+Pro:400,700,400italic,700italic">
    <link rel="stylesheet" href="css/default.css" media="screen">
  </head>
  <body>
    <textarea id="source">
class: center, middle, inverse
# 像黑客一样使用 

```
 _      _                  
| |    (_)                 
| |     _ _ __  _   ___  __
| |    | | '_ \| | | \ \/ /
| |____| | | | | |_| |>  < 
|______|_|_| |_|\__,_/_/\_\
```                           

## 命令行

```
idcu
2015.8.31
```
---
class: inverse
## 我喜欢使用命令行的原因
### 

- 功能强大

```
% history |
> awk '{CMD[$2]++;count++;}END \
> { for (a in CMD)print CMD[a] " " \
> CMD[a]/count*100 "% " a;}' |
> grep -v "./" |
> column -c3 -s " " -t |
> sort -nr |
> nl |
> head -n10
```
---
class: inverse
## 我喜欢使用命令行的原因
### 

```
 1  181  8.0516%    ls
 2  174  7.74021%   git
 3  167  7.42883%   cd
 4  163  7.25089%   jq
 5  154  6.85053%   l
 6  137  6.09431%   vim
 7  102  4.53737%   rm
 8  59   2.62456%   ll
 9  52   2.31317%   echo
10  49   2.17972%   ssh
```

([source](http://linux.byexamples.com/archives/332/what-is-your-10-common-linux-commands/))
---
class: inverse
## 我喜欢使用命令行的原因
### 

- 灵活高效

```
% cd photos

% ls -l | grep Mar
```
---
class: inverse
## 我喜欢使用命令行的原因
### 

- 能自动化

```
% ./script.sh
```
---
class: center, middle, inverse
## 魔法即将启幕......
---
class: center, middle, inverse
![Magic](img/unix-magic.jpg)
---
class: inverse
## 人非圣贤，孰能无过?
### 

- 重新输入，然后执行

- 稍加编辑，再来执行

- ?
---
class: inverse
## 人非圣贤，孰能无过?
### 

- 使用 ^ 删掉多余部分

```
% grep fooo /var/log/auth.log

% ^o

% grep foo /var/log/auth.log
```
---
class: inverse
## 人非圣贤，孰能无过?
### 

- 使用 ^old^new 换掉输错或输少的部分

```
% cat myflie

% ^li^il

% cat myfile

% ansible vod -m command -a 'uptim'

% ^im^ime

% ansible vod -m command -a 'uptime'
```
---
class: inverse
## 人非圣贤，孰能无过?
### 

- 使用 !:gs/old/new 将 old 全部换成 new

```
% ansible nginx -m command -a 'which nginx'

% !:gs/nginx/squid

% ansible squid -m command -a 'which squid'

% ^nginx^squid^:G # zsh
```
---
class: inverse
## 人非圣贤，孰能无过?
### 

#### 要记住的是：

- 一删

- 二换

- 三全变
---
class: inverse
## 忘记历史，就是背叛。
### 

- 了解历史记录的大小

```
% echo $HISTSIZE
1000
```

- 历史记录的保存位置

```
% echo $HISTFILE
/home/xiaodong/.zhistory
```

- 历史记录的保存大小

```
% echo $HISTFILESIZE # bash
1000

% echo $SAVEHIST     # zsh
1000
```
---
class: inverse
## 忘记历史，就是背叛。
### 

- 查看历史

```
% history

% history | less

1  hist
2  ./code/gs/update_system.pl -n
3  emerge -C chromium
4  emerge @preserved-rebuild
5* df -h
......

% history 5

% history | grep string
```
---
class: inverse
## 忘记历史，就是背叛。
### 

- 使用 Ctrl + r 逆向搜索历史命令

```
% 
(reverse-i-search)`h': history 5

```

- 使用 Ctrl + p 访问上一条命令

```
% history 5
[Ctrl + p]
```

- 使用 Ctrl + n 访问下一条命令

```
% 
[Ctrl + n]
```
---
class: inverse
## 忘记历史，就是背叛。
### 

- 使用 !! 执行上一条命令

```
% !!

% sudo !!

% apt-get install figlet
E: Could not open lock file /var/lib/dpkg/lock - open (13: Permission denied)
E: Unable to lock the administration directory (/var/lib/dpkg/), are you root?

% sudo !!
sudo apt-get install figlet
```
---
class: inverse
## 忘记历史，就是背叛。
### 

- 使用 !foo 执行以 foo 开头的命令

```
% !his
history
```
---
class: inverse
## 忘记历史，就是背叛。
### 

- 使用 !?foo 执行包含 foo 的命令

```
% !?is
echo $histchars
```
---
class: inverse
## 忘记历史，就是背叛。
### 

- 使用 !n 执行第 n 个命令

```
% !10
vim lib/TunePage.pm
```
---
class: inverse
## 忘记历史，就是背叛。
### 

- 使用 !-n 执行倒数第 n 个命令

```
% !-2
htop

% !-1 == !!
```

- Tip: 给命令提示符中增加历史命令编号

```
% export PS1='!\! \u@\h:\w\$ '
!998 idcu@idcu:~$
```
---
class: inverse
## 忘记历史，就是背叛。
### 

- 使用 !# 引用当前行

```
% cp filename filename.old

% cp filename !#:1.old
```
---
class: inverse
## 忘记历史，就是背叛。
### 

#### 关于历史引用，要记住的是：

- !!

- ![?]字符串

- ![-]数字

- !#
---
class: inverse
## 忘记历史，就是背叛。
### 

- 历史命令 Word 选取图

![history words](img/hist-word.png)
---
class: inverse
## 忘记历史，就是背叛。
### 

- 通过 !$ 得到上一条命令的最后一位参数

```
% mkdir videos

% cd !$

% 
[Alt + .]
```
---
class: inverse
## 忘记历史，就是背叛。
### 

- 通过 !^ 得到上一条命令的第一个参数

```
% ls /usr/share/doc /usr/share/man

% cd !^

%
[Ctrl + Alt + y]
```
---
class: inverse
## 忘记历史，就是背叛。
### 

- 通过 !:n 得到上一条命令第 n 个参数

```
% touch foo.txt bar.txt baz.txt

% vim !:2
vim bar.txt
```
---
class: inverse
## 忘记历史，就是背叛。
### 

- 通过 !:x-y 得到上一条命令从 x 到 y 的参数

```
% touch foo.txt bar.txt baz.txt

% vim !:1-2 
vim foo.txt bar.txt
```
---
class: inverse
## 忘记历史，就是背叛。
### 

- 通过 !:n* 得到上一条命令从 n 开始到最后的参数

```
% cat /etc/resolv.conf /etc/hosts /etc/hostname

% vim !:2*
vim /etc/hosts /etc/hostname
```
---
class: inverse
## 忘记历史，就是背叛。
### 

- 通过 !* 得到上一条命令的所有参数

```
% ls code src

% cp -r !*
```
---
class: inverse
## 忘记历史，就是背叛。
### 

#### 关于 Word 选取，要记住的是：

- n

- ^|$

- [n]*

- x-y

```
% !an:$

% !10:2-4

% !{an}2
```
---
class: inverse
## 忘记历史，就是背叛。
### 

- 利用 :h 选取路径开头

```
% ls /usr/share/fonts/truetype

% cd !$:h
cd /usr/share/fonts
```

- 相当于 dirname
---
class: inverse
## 忘记历史，就是背叛。
### 

- 利用 :t 选取路径结尾

```
% wget http://nginx.org/download/nginx-1.4.7.tar.gz

% tar zxvf !$:t
tar zxvf nginx-1.4.7.tar.gz
```

- 相当于 basename
---
class: inverse
## 忘记历史，就是背叛。
### 

- 利用 :r 选取文件名

```
% unzip filename.zip

% cd !$:r
cd filename
```
---
class: inverse
## 忘记历史，就是背叛。
### 

- 利用 :e 选取扩展名

```
% echo abc.jpg

% echo !$:e
echo .jpg # bash
.jpg
echo jpg  # zsh
jpg
```
---
class: inverse
## 忘记历史，就是背叛。
### 

- 利用 :p 打印命令行

```
% echo *
README.md css img index.html js

% !:p
echo *
```
---
class: inverse
## 忘记历史，就是背叛。
### 

- 利用 :s 做替换

```
% echo this that

% !:s/is/e
echo the that

```

- 惯用法: ^is^e
---
class: inverse
## 忘记历史，就是背叛。
### 

- 利用 :g 做全局操作

```
% echo abcd abef

% !:gs/ab/cd
echo cdcd cdef
cdcd cdef
```
---
class: inverse
## 忘记历史，就是背叛。
### 

- 利用 :u 将其更改为大写 (zsh)

```
% echo $histchars

% echo !$:u
echo $HISTCHARS
```
---
class: inverse
## 忘记历史，就是背叛。
### 

- 利用 :l 将其更改为小写 (zsh)

```
% echo !$:l
echo $histchars
```
---
class: inverse
## 忘记历史，就是背叛。
### 

#### 关于修饰符，要记住的是：

- h|t

- r|e

- p

- s

- g

- u|l

```
% ls /usr/share/fonts/opentype

% echo !$:t:u
echo OPENTYPE
```

---
class: inverse
## 忘记历史，就是背叛。
### 

- 历史展开模式

![History](img/hist.png)
---
class: inverse
## 常备锦囊，内藏妙计。
### 

- 使用 alias -s 定义后缀别名 (zsh)

```
% alias -s pl=perl

% script.pl
perl script.pl

% alias -s pdf=zathura

% vimbook.pdf
zathura vimbook.pdf
```
---
class: inverse
## 常备锦囊，内藏妙计。
### 

- 使用 {} 构造字符串

```
% cp file.c file.c.bak

% cp file.c{,.bak}

% echo cp file.c{,.bak}

% vim {a,b,c}file.c
vim afile.c bfile.c cfile.c

% vim [abc]file.c  # ?

% vim {a..c}file.c # bash

% setopt braceccl  # zsh

% vim {a-c}file.c  # zsh
```
---
class: inverse
## 常备锦囊，内藏妙计。
### 

- 使用 {} 构造字符串 (续)

```
% wget http://idcu.tk/img/{1..5}.jpg
1.jpg  2.jpg  3.jpg  4.jpg  5.jpg

% touch {01..5}.txt
01.txt  02.txt  03.txt  04.txt  05.txt

% touch {1..10..2}.txt
1.txt  3.txt  5.txt  7.txt  9.txt

% echo {1..10..-2} # zsh
9 7 5 3 1

% echo {9..1..2}   # bash
9 7 5 3 1
```
---
class: inverse
## 常备锦囊，内藏妙计。
### 

- 使用 {} 构造字符串 (续)

```
% mkdir -p 2014/{01..12}/{baby,photo}

% echo {{A..Z},{a..z},{0..9}}
```
---
class: inverse
## 常备锦囊，内藏妙计。
### 

- 使用 \`` 或 $() 做命令替换

```
% grep -l error *.pm # (1)
TunePage.pm

% vim TunePage.pm    # (2)

% vim `grep -l error *.pm`

% vim $(grep -l error *.pm)
```

- 嵌套时，$() 可读性更清晰，而 \`` 则较差

```
% vim $(grep -l failed $(date +'%Y%m%d').log)

% vim `grep -l failed \`date +'%Y%m%d'\`.log`
```
---
class: inverse
## 常备锦囊，内藏妙计。
### 

- 使用变量保存信息

```
% LOG=/var/log/emerge.log

% head $LOG

% grep -i compiling $LOG
```
---
class: inverse
## 常备锦囊，内藏妙计。
### 

- 使用 for ... in 重复执行命令

```
% figlet -f font-type-1 Linux # (1)
% figlet -f font-type-2 Linux # (2)
% figlet -f font-type-3 Linux # (3)
% ...

% cd /usr/share/figlet
% for font in *.flf
> do
>   echo $font
>   figlet -f $font Linux
> done

% for font in *.flf; do echo $font; figlet -f $font Linux; done
```
---
class: inverse
## 常备锦囊，内藏妙计。
### 

- 使用 for ... in 重复执行命令 (续)

```
% for dev in /dev/sd{a..d}
> do
>   hdparm -t $dev
> done
```
---
class: inverse
## 重要原则
### 

- Type less, accomplish more (少打多做)

- DRY, don't repeat yourself (不要重复你自己)

- Care about your tool (关心你的工具)
---
class: inverse
## 本讲之外
### 

- Tab 补全

- 使用通配符 (* ? [a-z] [0-9])

- 用快捷键编辑命令行

- 字符串处理

- 复合命令 (; &amp;&amp; ||)
---
class: inverse
## 扩展阅读
### 

```
- bash: man history

- zsh: man zshexpn

- Bash Reference Manual: 
  https://www.gnu.org/software/bash/manual/html_node/index.html

- A User's Guide to ZSH:
  http://zsh.sourceforge.net/Guide/zshguide.html

- Book: Unix Power Tools
```
---
class: center, middle, inverse
## Q &amp; A 
---
class: inverse
## 联系方式
### 

```
- Website: http://idcu.tk

- Twitter: http://twitter.com/idcu

- GitHub: http://github.com/idcu

- OsChina: http://git.oschina.net/idcu

- Coding: https://coding.net/u/idcu

- Email: idcu@qq.com
```
---
class: center, middle, inverse
## 谢谢大家！
---
class: center, middle, inverse
Made in [Remark](http://remarkjs.com)
    </textarea>
    <script src="js/remark.min.js" type="text/javascript"></script>
    <script type="text/javascript">
      var slideshow = remark.create({
        highlightStyle: 'monokai',
        highlightLanguage: 'remark'
      });
    </script>
  </body>
</html>
